﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;

namespace Updater
{
	class Program
	{
		static void Main(string[] args)
		{
			Process P = Process.Start(Updater.sTrinityPluginPath + "CheckSum.exe");
			if (P != null)
			{
				while (!P.HasExited)
				{
					Thread.Sleep(500);
				}
				Updater.UpdateAvailable();
				Console.ReadLine();
			}

		}

	}

	internal static class Updater
	{
		//
		private static readonly string GitHubUrl = "https://funkybot.googlecode.com/git/FunkyBot";
		private static readonly string GitHubProjectUrl = "https://funkybot.googlecode.com/git/FunkyBot/FunkyBot.csproj";
		private static readonly string RemoteChecksumUrl = "https://funkybot.googlecode.com/git/FunkyBot/checksum.xml";
		internal static string pathUpdater = Assembly.GetEntryAssembly().Location;
		internal static string sDemonBuddyPath = Path.GetDirectoryName(pathUpdater.Replace(@"Plugins\FunkyBot\Updater.exe", ""));
		internal static string sTrinityPluginPath = sDemonBuddyPath + @"\Plugins\FunkyBot\";
		internal static string pathUpdaterTempFolder = sTrinityPluginPath + @"\TEMP\";

		internal static bool UpdateAvailable()
		{
			Dictionary<string, string> GithubChecksumDict = GenerateDictionaryFromChecksumXML(RemoteChecksumUrl);
			Dictionary<string, string> LocalChecksumDict = GenerateDictionaryFromChecksumXML(sTrinityPluginPath + @"\checksum.xml");
			List<string> GithubFileList = ReturnGitHubContentFiles();

			List<string> FilesNeededUpdated = new List<string>();

			//find any new or missing files..
			foreach (var f in GithubFileList)
			{
				if (!LocalChecksumDict.ContainsKey(f))
				{
					FilesNeededUpdated.Add(f);
				}
				else if (!GithubChecksumDict.ContainsKey(f))
				{
					Console.WriteLine("Github Checksum failed for file {0}", f);
				}
				else if (GithubChecksumDict[f] != LocalChecksumDict[f])
				{
					FilesNeededUpdated.Add(f);
				}

			}

			if (FilesNeededUpdated.Count == 1 && FilesNeededUpdated[0].Contains("CheckSum")) return false;

			Console.WriteLine("Files Needed Updated: " + FilesNeededUpdated.Count);

			if (FilesNeededUpdated.Count > 0)
			{
				if (!Directory.Exists(pathUpdaterTempFolder))
					Directory.CreateDirectory(pathUpdaterTempFolder);

				foreach (var f in FilesNeededUpdated)
				{
					Console.WriteLine("File: " + f);
					string FullDirectoryPath = Path.GetFullPath(sTrinityPluginPath + f.Substring(0, f.LastIndexOf(Convert.ToChar("/"))));
					if (!Directory.Exists(FullDirectoryPath))
					{
						Directory.CreateDirectory(FullDirectoryPath);
						Console.WriteLine("Creating new dictionary {0}", FullDirectoryPath);
					}

					string FulltempPath = Path.GetFullPath(pathUpdaterTempFolder + f);
					string GitHubUrlFullPath = (GitHubUrl + f).Replace(" ", "%20");

					//File.Delete(FullPath);

					// Create a new WebClient instance.
					using (WebClient myWebClient = new WebClient())
					{
						try
						{
							myWebClient.DownloadFile(GitHubUrlFullPath, FulltempPath);
							Console.WriteLine("Downloaded file {0} to location {1}", GitHubUrlFullPath, FulltempPath);
						}
						catch (Exception ex)
						{
							Console.WriteLine("Error updating file {0} at location {1}", f, GitHubUrlFullPath);
							continue;
						}
					}

					string FullPath = Path.GetFullPath(sTrinityPluginPath + f);
					//Check if we should delete old file
					if (File.Exists(FullPath))
					{
						Console.WriteLine("Deleting Old File {0}", f);
						File.Delete(FullPath);
					}

					//Copy New File
					File.Move(FulltempPath, FullPath);
				}
				return true;
			}


			return false;
		}
		internal static List<string> ReturnGitHubContentFiles()
		{
			List<string> returnValues = new List<string>();

			try
			{
				using (XmlTextReader reader = new XmlTextReader(GitHubProjectUrl))
				{
					// simply (and easily) skip the junk at the beginning
					reader.MoveToContent();
					reader.ReadToDescendant("ItemGroup");


					if ((reader.NodeType == XmlNodeType.Element) &&
						  (reader.Name == "ItemGroup"))
					{
						while (reader.Read())
						{

							if ((reader.NodeType == XmlNodeType.Element) &&
								  (reader.IsStartElement()) &&
									reader.HasAttributes)
							{
								switch (reader.LocalName)
								{
									case "Content":
									case "None":
									case "Compile":
										string s = "/" + reader.GetAttribute(0);
										returnValues.Add(s.Replace(@"\", "/"));
										break;
								}
							}
						}
					}
				}


			}
			catch (Exception)
			{

			}

			return returnValues;
		}
		internal static Dictionary<string, string> GenerateDictionaryFromChecksumXML(string path)
		{
			Dictionary<string, string> returnValues = new Dictionary<string, string>();

			try
			{
				using (XmlTextReader reader = new XmlTextReader(path))
				{
					// simply (and easily) skip the junk at the beginning
					reader.MoveToContent();
					//reader.ReadToDescendant("FileList");

					while (reader.Read())
					{
						if ((reader.NodeType == XmlNodeType.Element) &&
							  (reader.IsStartElement()) &&
								reader.HasAttributes)
						{
							string fileName = reader.GetAttribute(0);
							string fileHash = reader.GetAttribute(1);
							returnValues.Add(fileName.Replace(@"\", "/"), fileHash);
						}

					}
				}
			}
			catch (Exception)
			{

			}

			return returnValues;
		}
	}
}
